package com.antler.luajavalibrary.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.antler.luajavalibrary.activity.ScriptActivity;
import com.antler.luajavalibrary.application.MyApplication;
import com.antler.luajavalibrary.inf.IScriptManager;
import com.antler.luajavalibrary.luajava.LuaJava;

public class ScriptService extends Service {
    private final static String TAG = "antler_" + ScriptService.class.getSimpleName();

    protected Thread mThread = null;

    protected Handler mHandler = null;

    private MyBinder mBinder = new MyBinder();

    public class MyBinder extends Binder {
        public ScriptService getService() {
            return ScriptService.this;
        }
    }

    protected static MediaProjection sMediaProjection = null;
    protected static VirtualDisplay sVirtualDisplay = null;
    protected static ImageReader sImageReader = null;

    @Override
    public void onCreate() {
        Log.v(TAG, "onCreate - Thread = " + Thread.currentThread().getName());
        super.onCreate();

        mHandler = new Handler(Looper.getMainLooper());

        init();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.v(TAG, "onStartCommand - startId = " + startId + ", Thread = " + Thread.currentThread().getName());
        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.v(TAG, "onBind - Thread = " + Thread.currentThread().getName());
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v(TAG, "onUnbind - Thread = " + Thread.currentThread().getName());
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.v(TAG, "onDestroy - Thread = " + Thread.currentThread().getName());
        super.onDestroy();

        stop();

        uninit();
    }

    void init() {
        Log.v(TAG, "init");

        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                requestScreenCapturePermission();
            }
        }, 200);
    }

    void uninit() {
        Log.v(TAG, "uninit");

        destroyScreenCapture();
    }

    public void start(final String script) {
        if (script == null || script.isEmpty()) {
            return;
        }

        if (mThread != null && mThread.isAlive()) {
            return;
        }

        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                LuaJava.openLibs();

                try {
                    LuaJava.doString(script);
                } catch (Exception e) {
                    final String msg = e.getMessage();
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(ScriptService.this.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                        }
                    });
                }

                LuaJava.closeLibs();
            }
        });

        mThread.start();
    }

    public void startWithFile(final String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return;
        }

        if (mThread != null && mThread.isAlive()) {
            return;
        }

        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                LuaJava.openLibs();

                try {
                    LuaJava.doFile(filePath);
                } catch (Exception e) {
                    final String msg = e.getMessage();
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(ScriptService.this.getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                        }
                    });
                }

                LuaJava.closeLibs();
            }
        });

        mThread.start();
    }

    public void stop() {
        LuaJava.doStop();
    }

    public void setCallback(IScriptManager.Callback callback) {
        LuaJava.setCallback(callback);
    }

    public void requestScreenCapturePermission() {
        Intent intent = new Intent(this, ScriptActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    protected static void destroyScreenCapture() {
        if (sImageReader != null) {
            sImageReader.close();
            sImageReader = null;
        }

        if (sVirtualDisplay != null) {
            sVirtualDisplay.release();
            sVirtualDisplay = null;
        }

        if (sMediaProjection != null) {
            sMediaProjection.stop();
            sMediaProjection = null;
        }
    }

    public static void setMediaProjection(MediaProjection mediaProjection) {
        destroyScreenCapture();

        sMediaProjection = mediaProjection;
        if (sMediaProjection != null) {
            DisplayMetrics metrics = MyApplication.getContext().getResources().getDisplayMetrics();

            sImageReader = ImageReader.newInstance(metrics.widthPixels, metrics.heightPixels, PixelFormat.RGBA_8888, 1); // PixelFormat.RGBX_8888

            sVirtualDisplay = sMediaProjection.createVirtualDisplay("ScreenCapture",
                    metrics.widthPixels, metrics.heightPixels, metrics.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                    sImageReader.getSurface(), null, null);
        }
    }

    public static Image getScreenCaptureImage() {
        if (sImageReader == null) {
            return null;
        }

        int try_count = 5;

        Image image = null;

        try {
            do {
                image = sImageReader.acquireLatestImage();
                Thread.sleep(20);
            } while (try_count-- > 0 && image == null);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return image;
    }
}